package com.topscomm.mis.cbb.pm.service.abs;

import com.topscomm.basic.BasicEntity;
import com.topscomm.basic.exception.ServiceException;
import com.topscomm.basic.util.PrimaryKeyUtil;
import com.topscomm.cbo.service.ICboApprovalFlowInsService;
import com.topscomm.mis.cbb.pm.api.ITaskService;
import com.topscomm.mis.cbb.pm.api.IWbsService;
import com.topscomm.mis.cbb.pm.base.pojo.CbbPmTaskEntity;
import com.topscomm.mis.cbb.pm.base.pojo.CbbPmWbsChangeDetailEntity;
import com.topscomm.mis.cbb.pm.base.pojo.CbbPmWbsChangeEntity;
import com.topscomm.mis.cbb.pm.base.pojo.CbbPmWbsEntity;
import com.topscomm.mis.cbb.pm.base.service.*;
import com.topscomm.mis.cbb.pm.util.FlowNode;
import com.topscomm.mis.cbb.pm.util.PmSystemConst;
import com.topscomm.pub.util.ConvertUtil;
import com.topscomm.pub.util.StringBufferProxy;
import com.topscomm.pub.vo.Page;
import com.topscomm.pub.vo.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@ConditionalOnMissingBean(ITaskService.class)
public abstract class AbstractTaskService implements ITaskService {
    @Autowired
    private ICbbPmTaskService cbbPmTaskService;
    @Autowired
    private ICbbPmWbsService cbbPmWbsService;
    @Autowired
    private ICbbPmWbsChangeService cbbPmWbsChangeService;
    @Autowired
    private ICbbPmTaskEditDocService cbbPmTaskEditDocService;
    @Autowired
    private ICbbPmTaskBackRecordService cbbPmTaskBackRecordService;
    @Autowired
    private ICboApprovalFlowInsService cboApprovalFlowInsService;
    @Autowired
    private ICbbPmWbsChangeDetailService cbbPmWbsChangeDetailService;

    @Override
    public Map<String, Object> getGanttInfo(Map<String, Object> paramMap) {
        return null;
    }

    @Override
    public Map<String, Object> insert(Map<String, Object> paramMap) {
        beforeInsert(paramMap);
        CbbPmTaskEntity cbbPmTaskEntity = new CbbPmTaskEntity();
        cbbPmTaskEntity.convertFromMap(paramMap);
        cbbPmTaskEntity = cbbPmTaskService.insert(cbbPmTaskEntity);
        Map<String, Object> dataMap = cbbPmTaskEntity.convertToMap();
        afterInsert(dataMap);
        return dataMap;
    }

    protected void beforeInsert(Map<String, Object> paramMap) throws ServiceException {
    }

    protected void afterInsert(Map<String, Object> paramMap) throws ServiceException {
    }


    @Override
    public void update(Map<String, Object> paraMap) {
        cbbPmTaskService.update(paraMap);
    }

    @Override
    public void delete(Map<String, Object> paraMap) {
        String ids = ConvertUtil.convertToString(paraMap.get("ids"));
        cbbPmTaskService.deleteByWhere(" id in (" + ids + ")");
    }

    @Override
    public Map<String, Object> load(Map<String, Object> paraMap) {
        Map<String, Object> taskInfo = cbbPmTaskService.queryMapById(paraMap.get("id").toString());
        this.loaded(taskInfo);
        return taskInfo;
    }

    protected void loaded(Map<String, Object> taskInfo) throws ServiceException {

    }

    @Override
    public Page list(Map<String, Object> paraMap, String sqlWhere) {
        Query query = new Query(paraMap);
        int totalCount = cbbPmTaskService.getCount(sqlWhere);
        List<Map<String, Object>> tempList = null;
        if (query.getPageSize() > 0) {
            tempList = cbbPmTaskService.queryMapForPage(sqlWhere, query.getCurrentPage(), query.getPageSize(),
                    query.getSidx(), query.getSord());
        } else {
            tempList = cbbPmTaskService.queryMapByWhere(sqlWhere);
        }
        return new Page(tempList, totalCount, query.getPageSize(), query.getCurrentPage());
    }

    @Override
    public void initFlowTask(Map<String, Object> paraMap, List<FlowNode> flowNodeList, Map<String, Object> paramMap,String parentCode, String flowinsid, Boolean findRound, int loopTimes, int useTimes) {
        return;
    }


    @Override
    public Map<String, Object> backRecordInfo(Map<String, Object> paraMap) {
        return cbbPmTaskBackRecordService.queryMapById(paraMap.get("id").toString());
    }
    /**
     * @description: 批量保存任务
     * @return void
     * @author: hudeyong
     * @date: 2023/6/25
     * @modify:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveBatchTask(Map<String, Object> taskInfo){
        //项目编辑中保存的生成一份历史
        CbbPmWbsChangeEntity cbbPmWbsChangeEntity = new CbbPmWbsChangeEntity();
        boolean fromProjectEdit = false;
        if (taskInfo.containsKey("fromProjectEdit")) {
            fromProjectEdit = true;
        }
        if (fromProjectEdit) {
            CbbPmWbsEntity cbbPmWbsEntity = cbbPmWbsService.queryObjectByWhere(" projectuucode='"+taskInfo.get("projectUUCode")+"'");
            //更新wbs
            cbbPmWbsChangeEntity = this.updateWbs(cbbPmWbsEntity);
            Map<String,Object> pmWbsChangeInfo = cbbPmWbsChangeEntity.convertToMap();
            this.backupTask(" projectuucode='"+taskInfo.get("projectUUCode")+"'",pmWbsChangeInfo);
        }
        List<Map<String, Object>> taskList = (List<Map<String, Object>>) taskInfo.get("tasklist");
        List<Map<String, Object>> updateList = taskList.stream().filter(item -> ConvertUtil.convertToInt(item.get("isAdd")) == PmSystemConst.CboYesNo.NO).collect(Collectors.toList());
        List<BasicEntity> tempList = new ArrayList<>();
        // 更新
        for(Map<String, Object> map : updateList){
            CbbPmTaskEntity pmTaskEntity = new CbbPmTaskEntity();
            pmTaskEntity.convertFromMap(map);
            tempList.add(pmTaskEntity);
        }
        cbbPmTaskService.updateBatch(tempList);
        taskList.removeAll(updateList);
        // 插入
        tempList = new ArrayList<>();
        for(Map<String, Object> map : taskList){
            CbbPmTaskEntity pmTaskEntity = new CbbPmTaskEntity();
            pmTaskEntity.convertFromMap(map);
            tempList.add(pmTaskEntity);
        }
        cbbPmTaskService.insertBatch(tempList);
    }

    public CbbPmWbsChangeEntity updateWbs(CbbPmWbsEntity cbbPmWbsEntity){
        // 插入wbs变更记录
        CbbPmWbsChangeEntity cbbPmWbsChangeEntity = new CbbPmWbsChangeEntity();
        cbbPmWbsChangeEntity.setProjectuucode(cbbPmWbsEntity.getProjectuucode());
        cbbPmWbsChangeEntity.setWbscode(cbbPmWbsEntity.getWbscode());
        cbbPmWbsChangeEntity.setChangetype(PmSystemConst.WbsChangeType.AUTOMATIC);
        cbbPmWbsChangeEntity.setChangereason("项目WBS编辑引起WBS变更");
        cbbPmWbsChangeEntity.setBeforeversion(cbbPmWbsEntity.getVersion());
        cbbPmWbsChangeEntity.setAfterversion(cbbPmWbsEntity.getVersion()+1);
        long[] arrayId = PrimaryKeyUtil.GeneIDs(cbbPmWbsChangeEntity.getTableName(), 1);
        cbbPmWbsChangeEntity.setId(arrayId[0]);
        cbbPmWbsChangeService.insert(cbbPmWbsChangeEntity);
        // wbs版本号加1
        cbbPmWbsEntity.setVersion(cbbPmWbsEntity.getVersion()+1);
        cbbPmWbsService.updateEntity(cbbPmWbsEntity);
        return cbbPmWbsChangeEntity;
    }
    /**
     * @description: 约束条件变更引起wbs任务变更
     * @return void
     * @author: hudeyong
     * @date: 2023/6/26
     * @modify:
     */
    @Transactional(rollbackFor = Exception.class)
    public void changeTaskByCommit(List<FlowNode> nodeList, String uuCode, boolean versionUpgrade) {
        // 查找uuCode下的所有任务
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle("{0} = '{1}'",CbbPmTaskEntity.FieldProjectuucode,uuCode);
        List<CbbPmTaskEntity> pmTaskEntities = cbbPmTaskService.queryByWhere(sql.toString());
        // nodeList中的节点是从开始节点到结束节点遍历的
        for(FlowNode nodeInfo : nodeList){
            String id = nodeInfo.getId();
            // 找到该节点的所有任务
            List<CbbPmTaskEntity> tempTaskList = pmTaskEntities.stream().filter(item -> item.getNodeid().equals(id)).collect(Collectors.toList());
            if(tempTaskList.size()>0) {
                //生成过任务，和原有任务比对
                //此时的人员
                List<Map<String, Object>> approvalUser = nodeInfo.getPlanUser();
                String newUserCode = approvalUser.stream().map(item -> ConvertUtil.convertToString(item.get("code"))).collect(Collectors.joining(","));
                String oldUserCode = tempTaskList.stream().map(item -> ConvertUtil.convertToString(item.getResponsibleusercode())).collect(Collectors.joining(","));
                //如果人员无变化，不管任务状态是否有变化，都不生成快照
                //如果人员有变化
                //任务未开始，不生成快照
                //任务进行中，原有任务关闭，生成快照，新任务轮次加一轮，重新开始
                //任务已完成，原有任务生成快照，新任务轮次加一轮，重新开始
            } else {
               // 未生成过任务，需要重新生成新任务
            }

        }
    }

    /**
     * @description: 任务备份快照
     * @return void
     * @author: hudeyong
     * @date: 2023/6/28
     * @modify:
     */
    @Override
    public void backupTask(String whereSql, Map<String,Object> wbsChangeInfo) {
        List<Map<String, Object>> cbbPmTaskList = cbbPmTaskService.queryMapByWhere(whereSql.toString());
        List<BasicEntity> pmWbsChangeDetailEntities = new ArrayList<>();
        for(Map<String, Object> cbbPmTask: cbbPmTaskList) {
            CbbPmWbsChangeDetailEntity pmWbsChangeDetailEntity = new CbbPmWbsChangeDetailEntity();
            pmWbsChangeDetailEntity.convertFromMap(cbbPmTask);
            pmWbsChangeDetailEntity.setWbschangeid(ConvertUtil.convertToLong(wbsChangeInfo.get("id")));
            pmWbsChangeDetailEntity.setWbsversion(ConvertUtil.convertToInt(wbsChangeInfo.get("beforeversion")));
            long[] arrayId = PrimaryKeyUtil.GeneIDs(pmWbsChangeDetailEntity.getTableName(), 1);
            pmWbsChangeDetailEntity.setId(arrayId[0]);
            pmWbsChangeDetailEntities.add(pmWbsChangeDetailEntity);
        }
        cbbPmWbsChangeDetailService.insertBatch(pmWbsChangeDetailEntities);
    }

    @Override
    public void changeTaskByFlow(String uuCode, List<FlowNode> nodeList, Map<String, Object> pmWbsInfo, String parentCode, String flowInsId) {}
    @Override
    public void changeTaskByNode(Map<String, Object> wbsInfo,FlowNode node,Map<String,Object> paraMap) {}

    @Override
    public void loseTask(List<FlowNode> nodeList, Boolean isSonFlow, String uuCode, String flowInsId) {}
}
